package com.qn.common.core.handler;

import com.qn.common.core.constant.enums.ResultCodeEnum;
import com.qn.common.core.exception.CustomException;
import com.qn.common.core.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;

/**
 * 全局异常处理
 *
 * @author Qning
 * @date 2021/05/30
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * -------- 通用异常处理方法 --------
     **/
    @ExceptionHandler(Throwable.class)
    public Result<Void> error(Exception e) {
        String description = e.getCause().getMessage();
        return Result.error(description);
    }

    /**
     * -------- 指定异常处理方法 --------
     **/
    @ExceptionHandler(NullPointerException.class)
    public Result<Void> error(NullPointerException e) {
        return Result.setResult(ResultCodeEnum.NULL_POINTER);
    }

    /**
     * 参数校验异常
     *
     * @param e e
     * @return {@link ResponseEntity}<{@link Result}>
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<Void> error(MethodArgumentNotValidException e) {
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        String description = allErrors.stream().map(DefaultMessageSourceResolvable::getDefaultMessage).reduce((x, y) -> x + "," + y).orElseGet(ResultCodeEnum.PARAM_ERROR::getMessage);
        return Result.setResult(ResultCodeEnum.PARAM_ERROR, description);
    }

    /**
     * sql执行异常
     *
     * @param e e
     * @return {@link ResponseEntity}<{@link Result}>
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public Result<Void> error(SQLIntegrityConstraintViolationException e) {
        return Result.setResult(ResultCodeEnum.SQL_EXCEPTION);
    }

    /**
     * -------- 自定义定异常处理方法 --------
     **/
    @ExceptionHandler(CustomException.class)
    public Result<Void> error(CustomException e) {
        return Result.error(e.getCode(), e.getMessage());
    }

}

